package com.ikas.ai.server.module.morningpaper.render;

import com.alibaba.fastjson.JSON;
import com.ikas.ai.server.module.morningpaper.consts.MorningPaperElementPriorities;
import com.ikas.ai.server.module.morningpaper.consts.MorningPaperNormalVariableNames;
import com.ikas.ai.server.module.morningpaper.model.dto.MorningPaperVariablesDto;
import com.ikas.ai.server.module.morningpaper.model.elements.MorningPaperTopElement;
import com.ikas.ai.server.module.morningpaper.model.po.MorningPaperOverhaulPlanPo;
import com.ikas.ai.server.module.morningpaper.model.po.MorningPaperVariablesPo;
import com.ikas.ai.server.module.morningpaper.service.MorningPaperHisService;
import com.ikas.ai.server.module.morningpaper.service.MorningPaperOverhaulPlanService;
import com.ikas.ai.server.module.morningpaper.service.MorningPaperVariablesService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author li.hexian
 * 早报变量生成器
 */
@Service
@Slf4j
public class MorningPaperVariablesRender {

    @Autowired
    MorningPaperVariablesService morningPaperVariablesService;
    @Autowired
    MorningPaperHisService morningPaperHisService;
    @Autowired
    MorningPaperOverhaulPlanService morningPaperOverhaulPlanService;
    @Autowired
    ConfigurableApplicationContext applicationContext;

    /**
     * 以Spring加载全部相关bean，并执行其render方法，填充dto。填充后销毁相关bean和相关容器
     *
     * @return MorningPaperVariablesDto
     */
    @Transactional
    public MorningPaperVariablesDto generateANewOne() {
        Map<String, MorningPaperVariablesPo> posMap = morningPaperVariablesService.getPosMap();
        Map<String, Object> transmitMap = new HashMap<>();
        MorningPaperVariablesDto doneMv;
        Map<String, MorningPaperTopElement> beansOfType = applicationContext.getBeansOfType(MorningPaperTopElement.class);
        try {
            MorningPaperVariablesDto mv = new MorningPaperVariablesDto();
            MorningPaperVariablesDto mvAfterFirstPriority = beansOfType.values().stream()
                    .filter(component -> component.getPriority().equals(MorningPaperElementPriorities.FIRST_PRIORITY))
                    .collect(Collectors.toList()).stream()
                    .map(component -> component.render(mv, posMap, transmitMap))
                    .reduce(mv, MorningPaperVariablesDto::merge);
            //根据维修计划更新mv
            checkValue(posMap, mv);
            MorningPaperVariablesDto mvAfterSecondPriority = beansOfType.values().stream()
                    .filter(component -> component.getPriority().equals(MorningPaperElementPriorities.SECOND_PRIORITY))
                    .collect(Collectors.toList()).stream()
                    .map(component -> component.render(mv, posMap, transmitMap))
                    .reduce(mv, MorningPaperVariablesDto::merge);
            checkValue(posMap, mv);
            MorningPaperVariablesDto firstMerge = mvAfterFirstPriority.merge(mvAfterSecondPriority);

            MorningPaperVariablesDto mvAfterThirdPriority = beansOfType.values().stream()
                    .filter(component -> component.getPriority().equals(MorningPaperElementPriorities.THIRD_PRIORITY))
                    .collect(Collectors.toList()).stream()
                    .map(component -> component.render(mv, posMap, transmitMap))
                    .reduce(mv, MorningPaperVariablesDto::merge);
            checkValue(posMap, mv);
            doneMv = firstMerge.merge(mvAfterThirdPriority);
            morningPaperVariablesService.save(doneMv, posMap);
        } finally {
            clean(posMap, transmitMap, beansOfType);
        }
        return doneMv;
    }

    /**
     * 在维修计划内的机组count和hours置为0
     *
     * @param posMap
     * @param mv
     */
    private void checkValue(Map<String, MorningPaperVariablesPo> posMap, MorningPaperVariablesDto mv) {
        //具体某个机组的启停次数是优先级为1的
        Map<String, List<MorningPaperOverhaulPlanPo>> planMap = morningPaperOverhaulPlanService.getPosMap();
        log.info("维修计划:{}", JSON.toJSONString(planMap));
        planMap.forEach((k, v) -> {
            List<MorningPaperNormalVariableNames> enumByMachineNo = MorningPaperNormalVariableNames.getEnumByMachineNo(k);
            if (CollectionUtils.isNotEmpty(enumByMachineNo)) {
                for (MorningPaperNormalVariableNames morningPaperNormalVariableNames : enumByMachineNo) {
                    log.info("维修机组:{},变量值置为0:{}", k, morningPaperNormalVariableNames);
                    MorningPaperVariablesPo morningPaperVariablesPo = posMap.get(morningPaperNormalVariableNames.name());
                    morningPaperVariablesPo.setValue("0");
                    posMap.put(morningPaperNormalVariableNames.name(), morningPaperVariablesPo);
                    //设置mv对应属性值为0
                    switch (morningPaperNormalVariableNames) {
                        case machineU01ConditionGPowerUpCount:
                            mv.setMachineU01ConditionGPowerUpCount(0L);
                            break;
                        case machineU02ConditionGPowerUpCount:
                            mv.setMachineU02ConditionGPowerUpCount(0L);
                            break;
                        case machineU03ConditionGPowerUpCount:
                            mv.setMachineU03ConditionGPowerUpCount(0L);
                            break;
                        case machineU04ConditionGPowerUpCount:
                            mv.setMachineU04ConditionGPowerUpCount(0L);
                            break;

                        case machineU01ConditionPPowerUpCount:
                            mv.setMachineU01ConditionPPowerUpCount(0L);
                            break;
                        case machineU02ConditionPPowerUpCount:
                            mv.setMachineU02ConditionPPowerUpCount(0L);
                            break;
                        case machineU03ConditionPPowerUpCount:
                            mv.setMachineU03ConditionPPowerUpCount(0L);
                            break;
                        case machineU04ConditionPPowerUpCount:
                            mv.setMachineU04ConditionPPowerUpCount(0L);
                            break;

                        case machineU01ConditionPCPowerUpCount:
                            mv.setMachineU01ConditionPCPowerUpCount(0L);
                            break;
                        case machineU02ConditionPCPowerUpCount:
                            mv.setMachineU02ConditionPCPowerUpCount(0L);
                            break;
                        case machineU03ConditionPCPowerUpCount:
                            mv.setMachineU03ConditionPCPowerUpCount(0L);
                            break;
                        case machineU04ConditionPCPowerUpCount:
                            mv.setMachineU04ConditionPCPowerUpCount(0L);
                            break;

                        case machineU01ConditionGPowerUpHours:
                            mv.setMachineU01ConditionGPowerUpHours(0.0);
                            break;
                        case machineU02ConditionGPowerUpHours:
                            mv.setMachineU02ConditionGPowerUpHours(0.0);
                            break;
                        case machineU03ConditionGPowerUpHours:
                            mv.setMachineU03ConditionGPowerUpHours(0.0);
                            break;
                        case machineU04ConditionGPowerUpHours:
                            mv.setMachineU04ConditionGPowerUpHours(0.0);
                            break;

                        case machineU01ConditionPPowerUpHours:
                            mv.setMachineU01ConditionPPowerUpHours(0.0);
                            break;
                        case machineU02ConditionPPowerUpHours:
                            mv.setMachineU02ConditionPPowerUpHours(0.0);
                            break;
                        case machineU03ConditionPPowerUpHours:
                            mv.setMachineU03ConditionPPowerUpHours(0.0);
                            break;
                        case machineU04ConditionPPowerUpHours:
                            mv.setMachineU04ConditionPPowerUpHours(0.0);
                            break;

                        case machineU01ConditionPCPowerUpHours:
                            mv.setMachineU01ConditionPCPowerUpHours(0.0);
                            break;
                        case machineU02ConditionPCPowerUpHours:
                            mv.setMachineU02ConditionPCPowerUpHours(0.0);
                            break;
                        case machineU03ConditionPCPowerUpHours:
                            mv.setMachineU03ConditionPCPowerUpHours(0.0);
                            break;
                        case machineU04ConditionPCPowerUpHours:
                            mv.setMachineU04ConditionPCPowerUpHours(0.0);
                            break;
                    }
                }
            }
        });
    }

    /**
     * 销毁相应容器
     *
     * @param posMap
     * @param transmitMap
     * @param beansOfType
     */
    private void clean(Map<String, MorningPaperVariablesPo> posMap, Map<String, Object> transmitMap, Map<String, MorningPaperTopElement> beansOfType) {
        posMap.clear();
        transmitMap.clear();
        for (MorningPaperTopElement bean : beansOfType.values()) {
            applicationContext.getBeanFactory().destroyBean(bean);
        }
    }

}
